import time

import gradio as gr
import numpy as np
import pandas as pd
import plotly.express as px

from control import BccControl

# 预置模拟日志数据
initial_log = """2023-10-01 09:00:00 孔位1 投料1000个
2023-10-01 09:00:05 孔位3 投料1000个
2023-10-01 09:00:10 孔位5 投料1001个
2023-10-01 09:00:15 孔位7 投料1000个"""


def toggle_all():
    return [False] * 24  # 反选逻辑


def select_all():
    return [True] * 24  # 全选逻辑

def get_motor_data():
    x = np.linspace(0, 10, 50)
    current = np.sin(x) * 5 + np.random.normal(0, 0.5, 50)
    speed = np.cos(x) * 50 + np.random.normal(0, 5, 50)
    position = np.cumsum(speed) * 0.1

    df_current = pd.DataFrame({
        "x": x,
        "value": current,
        "parameter": "电流 (A)"
    })
    df_speed = pd.DataFrame({
        "x": x,
        "value": speed,
        "parameter": "速度 (rpm)"
    })
    df_position = pd.DataFrame({
        "x": x,
        "value": position,
        "parameter": "位置 (mm)"
    })
    df = pd.concat([df_current, df_speed, df_position], ignore_index=True)
    return df

def process(start_btn, selected_holes, quantity, progress=gr.Progress()):
    if not start_btn:
        return gr.update(), initial_log

    selected = [i + 1 for i, checked in enumerate(selected_holes) if checked]
    if not selected:
        raise gr.Error("请至少选择一个孔位！")
    if quantity < 1:
        raise gr.Error("投料数量必须大于0！")

    log_content = []
    for idx, hole in enumerate(selected, 1):
        # 模拟处理过程
        time.sleep(1)
        progress(idx / len(selected), desc=f"正在处理孔位 {hole}")
        log_entry = f"{time.strftime('%Y-%m-%d %H:%M:%S')} 孔位{hole} 投料{quantity}个"
        log_content.append(log_entry)

    return "\n".join(log_content), "\n".join(log_content)

if __name__ == '__main__':
    bcc_control = BccControl(port="COM8")

    with gr.Blocks() as demo:
        with gr.Tab("单个投料"):
            with gr.Row():
                count_input = gr.Textbox(label="输入计数个数", placeholder="例如：10")
            with gr.Row():
                connect_button = gr.Button("连接串口")
                disconnect_button = gr.Button("关闭串口")
            with gr.Row():
                start_device_button = gr.Button("启动设备",  variant="primary")
                stop_device_button = gr.Button("关闭设备")
            with gr.Row():
                start_count_button = gr.Button("开始计数", variant="primary")
                clear_count_button = gr.Button("清空计数")
                get_count_button = gr.Button("查看计数")
            with gr.Row():
                output_display = gr.Textbox(label="当前颗粒个数", interactive=False)

            # 绑定功能
            connect_button.click(bcc_control.connect_serial)
            disconnect_button.click(bcc_control.disconnect_serial)
            start_device_button.click(bcc_control.start_device, outputs=output_display)
            stop_device_button.click(bcc_control.stop_device, outputs=output_display)
            start_count_button.click(bcc_control.start_count, inputs= count_input, outputs=output_display)
            clear_count_button.click(bcc_control.clear_count, outputs=output_display)
            get_count_button.click(bcc_control.get_count, outputs=output_display)
        with gr.Tab("高通量投料"):
            # 孔位选择区域
            checkbox_list = []
            number_list = []
            with gr.Column():
                # 24个孔位分为6行，每行4个
                for row in range(2):
                    with gr.Row():
                        for col in range(12):
                            idx = row * 12 + col
                            if idx >= 24:
                                break
                            with gr.Column(scale=1, min_width=100):  # 可通过调整 scale 和 min_width 来控制宽度
                                chk = gr.Checkbox(label=f"孔位{idx + 1}", value=False, interactive=True)
                                # 数字输入框去掉标签，或换成更简短的标签，以减少占用面积
                                num = gr.Number(value=0, interactive=True, label="", show_label=False)
                                checkbox_list.append(chk)
                                number_list.append(num)
            # 控制按钮
            with gr.Row():
                all_btn = gr.Button("全选")
                invert_btn = gr.Button("反选")
            # 投料参数设置
            with gr.Row():
                quantity = gr.Number(
                    label="投料数量",
                    minimum=1,
                    value=1000,
                    precision=0,
                    interactive = True
                )
            # 进度显示
            progress = gr.Progress()
            # 日志窗口
            log_window = gr.Textbox(
                label="操作日志",
                value=initial_log,
                lines=10,
                interactive=False
            )
            # 开始按钮
            start_btn = gr.Button("开始投料", variant="primary")
            # 事件绑定
            all_btn.click(select_all, outputs=checkbox_list)
            invert_btn.click(toggle_all, outputs=checkbox_list)
        with gr.Tab("设置/debug"):
            with gr.Row():
                avg_weight = gr.Number(label="颗粒平均重量 (mg)", value=0.1, precision=2,interactive = True)
                debug_mode = gr.Checkbox(label="启用调试模式", value=False)
            with gr.Row():
                save_btn = gr.Button("保存设置", variant="primary")
                refresh_btn = gr.Button("刷新状态")
            gr.Markdown("## 系统状态监控")
            with gr.Row():
                motor_status = gr.Textbox(label="电机状态", value="已连接", interactive=False)
                fpga_status = gr.Textbox(label="FPGA连接状态", value="已连接", interactive=False)
            gr.Markdown("## 检测输出数据")
            with gr.Row():
                with gr.Column():
                    detection_output = gr.Textbox(label="检测数据", value="暂无数据", lines=5, interactive=False)
                with gr.Column():
                    motor_chart = gr.LinePlot(
                        value=get_motor_data(),
                        x="x",
                        y="value",
                        color="parameter",
                        label="电机状态实时监控",
                        height=200,
                        width=600
                    )

    # 启动应用
    demo.launch()